package com.itech.stocks;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

import com.itech.stocks.Stock.Type;


public class StockService {

	private static final String EQUIT_CONFIG = "EQUITY_CONFIG.properties";
	private static final String ALERT_CONFIG = "ALERT_CONFIG.properties";
	private static final String FNO_CONFIG = "FNO_CONFIG.properties";
	private static boolean isConsole = false;
	private static boolean alert = true;
	private static boolean print = true;
	private final Map<String, Stock> eqStocksMap =  new HashMap<String, Stock>();
	private final Map<String, List<StockAlert>> alertStocksMap =  new HashMap<String, List<StockAlert>>();
	private final Utils utils = new Utils();
	private final boolean isAllowResetCounter = true;

	public static void main(String[]  args) throws InterruptedException {
		StockService service = new StockService();
		service.loadConfiguration();
		if (isConsole) {
			service.getStockPrice(args);
		} else {
			int timeInMin = Integer.parseInt(args[0]);
			int refreshIntervalSeconds = Integer.parseInt(args[1]);
			long startTime = System.currentTimeMillis();
			long exitTime = startTime + timeInMin * 60 * 1000;
			if (args.length > 2 && args[2] != null) {
				if ("noAlert".equals(args[2])) {
					alert = false;
					print = true;
				} else if ("noPrint".equals(args[2])) {
					alert = true;
					print = false;
				}
			}
			while (exitTime > System.currentTimeMillis()) {
				System.out.println("\nRefreshing prices...");
				for (Entry<String, Stock> entry : service.eqStocksMap.entrySet()) {
					//String stockId = entry.getKey();
					Stock stock = entry.getValue();
					StockPrice stockPrice = service.utils.getStockPriceFor(stock);
					if (stockPrice != null) {
						stock.setStockPrice(stockPrice);
						if (print) {
							System.out.println("Stock:\n" + stock);
						}
						if (alert) {
							service.checkForAlert(stock);
						}
					}
				}
				Thread.sleep(refreshIntervalSeconds * 1000);
			}
		}


		//Stock stock = utils.getStockDetailsFor(new String[]{"UNITEC", "P", "27-Aug-2009", "8000"}, true);
		//StockPrice stock = utils.getStockDetailsFor(new String[]{"UNITEC"}, false);
		//System.out.println(stock);
		//getStockPrice(args);
	}

	private void checkForAlert(Stock stock) {
		List<StockAlert> alertList = alertStocksMap.get(stock.getStockId());
		if (alertList == null){
			return;
		}
		for (StockAlert stockAlert : alertList) {
			boolean alert = false;
			if (StockAlert.Criteria.LT.equals(stockAlert.getCriteria())) {
				alert = stock.getStockPrice().getLastTradePrice() < stockAlert.getPrice();
			} else if (StockAlert.Criteria.GT.equals(stockAlert.getCriteria())) {
				alert = stock.getStockPrice().getLastTradePrice() > stockAlert.getPrice();
			} else if (StockAlert.Criteria.EQ.equals(stockAlert.getCriteria())) {
				alert = stock.getStockPrice().getLastTradePrice() == stockAlert.getPrice();
			}
			if (!alert) {
				if (isAllowResetCounter) {
					stockAlert.resetCounter();
				}
				continue;
			}
			if (alert && (stockAlert.getAlertCount() == -1 ||
					(stockAlert.getAlertCounter() < stockAlert.getAlertCount()))) {
				stockAlert.increaseCounter();
				String message = "\n\nStock: \n" + stock + "\nAlert: \n" + stockAlert;
				System.out.println("\n\nStock: \n" + stock + "\nAlert: \n" + stockAlert);
			}

		}

	}

	private void loadConfiguration() {
		//Load equity config
		loadEquityConfig();
		loadFNOConfig();
		loadAlertConfig();
		isConsole = false;
	}

	private void loadAlertConfig() {
		Properties properties = loadProperties(ALERT_CONFIG);
		for (Entry<Object, Object> entry : properties.entrySet()) {
			String value = (String) entry.getValue();
			Map<String, String> dataMap = new HashMap<String, String>();
			String[] values = value.split(",");
			for (String v : values) {
				String[] keyVal = v.split("=");
				dataMap.put(keyVal[0].trim(), keyVal[1].trim());
			}
			StockAlert stockAlert = new StockAlert();
			String stockId = dataMap.get(StockAlert.STOCK_ID);
			stockAlert.setStockId(stockId);
			Stock stock = eqStocksMap.get(stockId);
			if (stock == null) {
				System.out.println("No stock config available for id-" + stockId);
				continue;
			}
			stockAlert.setSymbol(stock.getSymbol());
			List<StockAlert> alertList = alertStocksMap.get(stockId);
			if (alertList == null) {
				alertList = new ArrayList<StockAlert>();
				alertStocksMap.put(stockId, alertList);
			}

			stockAlert.setAlertCount(Integer.parseInt(dataMap.get(StockAlert.ALERT_COUNT)));
			stockAlert.setPrice(Double.parseDouble(dataMap.get(StockAlert.PRICE)));
			stockAlert.setCriteria(StockAlert.Criteria.valueOf(dataMap.get(StockAlert.CRITERIA)));
			alertList.add(stockAlert);
		}
	}

	private void loadFNOConfig() {
		Properties fnoProperties = loadProperties(FNO_CONFIG);
		Map<String, Stock> map = getStockMap(fnoProperties, true);
		eqStocksMap.putAll(map);
	}

	private void loadEquityConfig() {
		Properties eqProperties = loadProperties(EQUIT_CONFIG);
		Map<String, Stock> map = getStockMap(eqProperties, false);
		eqStocksMap.putAll(map);
	}

	private Map<String, Stock> getStockMap(Properties properties, boolean isFNO) {
		Map<String, Stock> stocksMap = new HashMap<String, Stock>();

		for (Entry<Object, Object> entry : properties.entrySet()) {
			String stockId = (String) entry.getKey();
			String value = (String) entry.getValue();
			Map<String, String> dataMap = new HashMap<String, String>();
			String[] values = value.split(",");
			for (String v : values) {
				String[] keyVal = v.split("=");
				dataMap.put(keyVal[0].trim(), keyVal[1].trim());
			}
			Stock stock = new Stock();
			String symbol = dataMap.get(Stock.SYMBOL);
			stock.setSymbol(symbol);
			stocksMap.put(stockId, stock);
			stock.setStockId(stockId);
			stock.setCompanyName(dataMap.get(Stock.COMPANY));
			stock.setExpiryDate(dataMap.get(Stock.EXPIRY_DATE));
			stock.setFnoType(dataMap.get(Stock.FNO_TYPE));
			stock.setStrikePrice(dataMap.get(Stock.STRIKE_PRICE));
			if (dataMap.get(Stock.INDEX_TYPE) != null) {
				stock.setIndexType(Stock.IndexType.valueOf(dataMap.get(Stock.INDEX_TYPE)));
			}
			if (isFNO) {
				stock.setType(Type.FNO);
			} else {
				stock.setType(Type.EQUITY);
			}

		}
		return stocksMap;
	}

	private Properties loadProperties(String fileName) {
		Properties properties = new Properties();
		try {
			InputStream in = new FileInputStream(new File(fileName));
			properties.load(in);
			in.close();
		} catch (IOException e) {
			System.out.println("Unable to load properties from-" + fileName + ";Cause:" + e.getMessage());
		}
		return properties;
	}




	private void getStockPrice(String[] args)
	throws InterruptedException {
		int startCount = 2;
		boolean yahoo = false;
		boolean icici = false;
		if ("YAHOO".equalsIgnoreCase(args[2])) {
			yahoo = true;
			startCount = 3;
			System.out.println("Tracking started using YAHOO.");
		} else if ("ICICI".equalsIgnoreCase(args[2])) {
			icici = true;
			startCount = 3;
			System.out.println("Tracking started using ICICI.");
		} else {
			icici = true;
			System.out.println("Tracking started using ICICI.");
		}

		Utils utils = new Utils();
		int timeInMin = Integer.parseInt(args[0]);
		int refreshIntervalSeconds = Integer.parseInt(args[1]);
		long startTime = System.currentTimeMillis();
		long exitTime = startTime + timeInMin * 60 * 1000;
		while (exitTime > System.currentTimeMillis()) {
			System.out.println("Refreshing prices...");
			for (int i = startCount; i < args.length; i++) {
				try {
					double value = 0;
					if (yahoo) {
						value = utils.getLastPriceFromYahooF(args[i]);
					} else if (icici) {
						value = utils.getLastTradePrice(args[i]);
					}
					System.out.println(args[i] + " : " + value);
				} catch (Exception e) {
					System.out.println("error: " + e.getMessage());
				}
			}
			Thread.sleep(refreshIntervalSeconds * 1000);
		}
	}


}
